#ifndef _DISTRIBUTED_COUNTER_H
#define _DISTRIBUTED_COUNTER_H

#include <pthread.h>
#include <assert.h>
#include <sys/types.h> // for off_t

/** class to implement a distributed counter that can safely be incremented and decreemnted 
    by multiple threads 
*/

class DistributedCounter {
private:
  pthread_mutex_t mutex; // the mutex that protects the counter
  off_t counter; // the counter (off_t so that we can count a lot)

  DistributedCounter(DistributedCounter&); // disable copy constructor
  DistributedCounter& operator = (const DistributedCounter&); // same for assignment
public:
  // constructor. Parameter is initial value
  DistributedCounter(off_t _initial);
  
  // destructor
  ~DistributedCounter(void);

  // increment and return the count atomicaly
  off_t Increment(off_t _increment);

  // decrement and return the count atomicaly
  off_t Decrement(off_t _decrement);
};


inline  DistributedCounter::DistributedCounter(off_t _initial):counter(_initial){
  pthread_mutex_init(&mutex,NULL);
}
  
inline DistributedCounter::~DistributedCounter(void){
  pthread_mutex_destroy(&mutex);
}

inline off_t DistributedCounter::Increment
(off_t _increment){
  pthread_mutex_lock(&mutex);
  counter+=_increment;
  off_t ret=counter;
  pthread_mutex_unlock(&mutex);
  return ret;
}

inline off_t DistributedCounter::Decrement
(off_t _decrement){
  pthread_mutex_lock(&mutex);
  assert(counter>0); // it is not alowed to decrement an already 0 counter
  counter-=_decrement;
  off_t ret=counter;
  pthread_mutex_unlock(&mutex);
  return ret;
}


#endif // _DISTRIBUTED_COUNTER_H
